<template>
  <view class="box">
    <image
      style="position: absolute; z-index: 1; width: 100%; height: 100vh"
      src="@/static/image/game2/background.png"
      mode="scaleToFill"
    />
    <view style="display: flex; align-items: center; justify-content: center; height: 170rpx">
      <image class="time-box" src="@/static/image/game2/time-background.png" mode="scaleToFill" />
      <text class="time">时间 {{ timeM }}:{{ timeS }}</text>
    </view>
    <view class="main">
      <view style="margin: 0 26rpx 0 16rpx">
        <view v-if="!isTypeSelect" style="height: 102rpx">
          <text v-if="isTypeSelect">1-9</text>
        </view>
        <view class="desc-box" v-else>
          <text class="desc-text">请从1-{{ gridCount }}按顺序依次点击数字</text>
          <text class="desc-text desc-text-border">请从1-{{ gridCount }}按顺序依次点击数字</text>
        </view>
      </view>
      <view style="position: relative; height: 764.99rpx; margin-top: 66rpx">
        <image
          style="position: absolute; z-index: 1; width: 100%; height: 764.99rpx"
          src="@/static/image/game2/grid-background.png"
          mode="scaleToFill"
        />
        <!-- 随机数 -->
        <view class="row-box">
          <view
            class="row"
            :style="{ height: `${100 / gridAttrs.length}%` }"
            v-for="(row, rowIndex) in gridAttrs"
            :key="rowIndex"
          >
            <view
              @tap="gridEvent(rowIndex, colIndex, col)"
              :class="[
                'grid',
                (rowIndex * gridSize + colIndex) % 2 == 0 ? 'grid-even' : 'grid-odd',
                selectedGrids.includes(rowIndex * gridSize + colIndex) ? 'grid-selected' : '',
                rowIndex % 2 == 1 && (rowIndex * gridSize + colIndex) % 2 == 0
                  ? gridSize % 2 == 0
                    ? 'grid-even-even'
                    : ''
                  : gridSize % 2 == 0 && rowIndex % 2 == 1
                    ? 'grid-odd-even'
                    : '',
                gridSize == 5 ? colorNameAttr[rowIndex * gridSize + colIndex] : '',
                selectError.includes(rowIndex * gridSize + colIndex) ? 'grid-error' : ''
              ]"
              v-for="(col, colIndex) in row"
              :key="colIndex"
              :id="`grid-${rowIndex}-${colIndex}`"
            >
              <text class="grid-number" :style="[gridFontSize]">{{ col ? col : '' }}</text>
              <text class="grid-number grid-number-border" :style="[gridFontSize]">{{
                col ? col : ''
              }}</text>
            </view>
          </view>
        </view>
      </view>
    </view>
    <!-- 难度选择 -->
    <view class="mode" v-if="!isTypeSelect">
      <view class="mode-content">
        <text class="mode-name" style="margin-bottom: 128rpx">选择难度</text>
        <view @tap="changeMode('easy')" class="mode-easy">
          <image class="back-image" src="@/static/image/game2/green.png" mode="scaleToFill" />
          <text class="mode-name">简 单</text>
        </view>
        <view @tap="changeMode('primary')" class="mode-primary">
          <image class="back-image" src="@/static/image/game2/yellow.png" mode="scaleToFill" />
          <text class="mode-name">普 通</text>
        </view>
        <view @tap="changeMode('difficult')" class="mode-difficult">
          <image class="back-image" src="@/static/image/game2/red.png" mode="scaleToFill" />
          <text class="mode-name">困 难</text>
        </view>
      </view>
    </view>
    <!-- 开始游戏 -->
    <view
      class="start-box"
      style="align-items: flex-end; padding-bottom: 364rpx"
      v-if="isStart && isTypeSelect"
    >
      <view @tap="startGame" class="start-btn">
        <image class="back-image" src="@/static/image/game2/green.png" mode="scaleToFill" />
        <text class="mode-name">开始游戏</text>
      </view>
    </view>
    <!-- 开始倒计时 -->
    <view class="start-down" v-if="startDown">
      <text class="start-down-name">{{ startDownCount }}</text>
    </view>
    <!-- 游戏结束 -->
    <view class="game-over" v-if="isGameOver">
      <view class="over-box">
        <view class="over-main">
          <text class="over-name">完成训练!</text>
          <view class="game-time-box">
            <view style="position: relative; display: flex">
              <text class="time-name">耗时</text>
              <text class="time-name time-name-border">耗时</text>
            </view>
            <view style="position: relative; display: flex; margin: 0 8rpx" v-if="gameOverM > 0">
              <text class="game-time">{{ gameOverM }}</text>
              <text class="game-time game-time-border">{{ gameOverM }}</text>
            </view>
            <view style="position: relative; display: flex" v-if="gameOverM > 0">
              <text class="time-name">分</text>
              <text class="time-name time-name-border">分</text>
            </view>
            <view style="position: relative; display: flex; margin: 0 8rpx">
              <text class="game-time">{{ gameOverS < 10 ? `0${gameOverS}` : gameOverS }}</text>
              <text class="game-time game-time-border">{{
                gameOverS < 10 ? `0${gameOverS}` : gameOverS
              }}</text>
            </view>
            <view style="position: relative; display: flex">
              <text class="time-name">秒</text>
              <text class="time-name time-name-border">秒</text>
            </view>
          </view>
        </view>
        <view class="over-btn">
          <view @tap="resetGame" class="reset-btn" style="margin-bottom: 48rpx">
            <image class="back-image" src="@/static/image/game2/red.png" mode="scaleToFill" />
            <text class="mode-name">再次训练</text>
          </view>
          <view @tap="quitGame" class="quit-btn">
            <image class="back-image" src="@/static/image/game2/yellow.png" mode="scaleToFill" />
            <text class="mode-name">退出训练</text>
          </view>
        </view>
      </view>
    </view>
    <!-- 游戏超时 -->
    <view class="game-time-over" v-if="isGameTimeOver">
      <view style="display: flex; flex-direction: column; align-items: center">
        <view style="margin-bottom: 300rpx">
          <text class="game-time-over-name">游戏超时自动结束</text>
        </view>
        <view class="over-btn">
          <view @tap="resetGame" class="reset-btn" style="margin-bottom: 48rpx">
            <image class="back-image" src="@/static/image/game2/red.png" mode="scaleToFill" />
            <text class="mode-name">再次训练</text>
          </view>
          <view @tap="quitGame" class="quit-btn">
            <image class="back-image" src="@/static/image/game2/yellow.png" mode="scaleToFill" />
            <text class="mode-name">退出训练</text>
          </view>
        </view>
      </view>
    </view>
  </view>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { onLoad, onReady, onUnload } from '@dcloudio/uni-app'

const timeM = ref<string>('00')
const timeS = ref<string>('00')
const gameOverM = ref<number>(0)
const gameOverS = ref<number>(0)
// const gameOverTime = ref<number>()
const modeType = ref<string>('easy')
const isTypeSelect = ref<boolean>(false)
const isStart = ref<boolean>(false)
const isGameOver = ref<boolean>(false)
const isGameTimeOver = ref<boolean>(false)
const startDown = ref<boolean>(false)
const startDownCount = ref<number>(3)

const gridFontSize = ref<any>({})

let gridSize: number = 3
let gridCount: number = 9
let gridAttr: number[] = []
const gridAttrs = ref<number[][]>([])

const colorNameAttr = ref<string[]>([])

const selectGridIndex = ref(0)
const selectedGrids = ref<number[]>([])
const selectError = ref<number[]>([])

let timer: any = null
let touchAudio: any = null

// 事件
const gridEvent = (rowIndex: number, colIndex: number, col: number) => {
  if (col == selectGridIndex.value + 1) {
    const gridIndex = rowIndex * gridSize + colIndex
    if (!selectedGrids.value.includes(gridIndex)) {
      selectedGrids.value.push(gridIndex)
    }
    playAudio('success')
    console.log('选择正确')
    if (col == gridCount) {
      console.log('游戏结束')
      isGameOver.value = true
      clearInterval(timer)
      gameOverM.value = Number(timeM.value)
      gameOverS.value = Number(timeS.value)

      touchAudio.stop()
      selectError.value = []
    } else {
      selectGridIndex.value++
    }
  } else {
    const gridIndex = rowIndex * gridSize + colIndex
    if (!selectError.value.includes(gridIndex)) {
      selectError.value.push(gridIndex)
    }
    setTimeout(() => {
      selectError.value = []
    }, 100)
    playAudio('error')
    console.log('选择错误')
  }
}

onLoad(() => {
  if (timer) {
    clearInterval(timer)
  }
  timeM.value = '00'
  timeS.value = '00'
  selectGridIndex.value = 0
  selectedGrids.value = []
  selectError.value = []
  startDownCount.value = 3

  if (touchAudio) {
    try {
      touchAudio.stop()
      // touchAudio.destroy()
      touchAudio = null
    } catch (e) {
      console.log(e)
    }
  }
})

onReady(() => {
  isTypeSelect.value = false
  isStart.value = false
  startDown.value = false
  isGameOver.value = false
  initArray()
})

const playAudio = (type: any) => {
  const playList: any = {
    success: '/static/video/game2/success.mp3',
    error: '/static/video/game2/error.mp3'
  }

  if (touchAudio) {
    try {
      touchAudio.stop()
      // touchAudio.destroy()
    } catch (e) {
      console.log(e)
    }
  }

  touchAudio = uni.createInnerAudioContext()
  touchAudio.autoplay = false
  touchAudio.src = playList[type]
  touchAudio.onCanplay(() => {
    touchAudio.play()
  })

  touchAudio.onError(() => {
    touchAudio.destroy()
  })

  touchAudio.onPause(() => {
    touchAudio.destroy()
  })

  touchAudio.onStop(() => {
    touchAudio.destroy()
  })

  touchAudio.onEnded(() => {
    setTimeout(() => {
      touchAudio.destroy()
    }, 500)
  })
}

onUnload(() => {
  if (touchAudio) {
    try {
      touchAudio.stop()
      touchAudio.destroy()
      touchAudio = null
    } catch (e) {
      console.log(e)
    }
  }
})

// 难度选择
const changeMode = (type: string) => {
  modeType.value = type
  startDown.value = false
  isGameOver.value = false
  if (timer) {
    clearInterval(timer)
  }
  timeM.value = '00'
  timeS.value = '00'
  switch (type) {
    case 'easy':
      gridSize = 3
      gridCount = 9
      gridFontSize.value = {
        fontSize: '92rpx'
      }
      break
    case 'primary':
      gridSize = 4
      gridCount = 16
      gridFontSize.value = {
        fontSize: '84rpx'
      }
      break
    case 'difficult':
      gridSize = 5
      gridCount = 25
      gridFontSize.value = {
        fontSize: '76rpx'
      }
      randomColor()
      break
    default:
      gridSize = 3
      gridCount = 9
      gridFontSize.value = {
        fontSize: '92rpx'
      }
      break
  }

  isTypeSelect.value = true
  isStart.value = true
}

// 5阶 随机颜色
const randomColor = () => {
  const colorName = ['grid-color-1', 'grid-color-2', 'grid-color-3', 'grid-color-4']
  colorNameAttr.value = Array.from({ length: gridCount }, () => {
    return colorName[Math.floor(Math.random() * colorName.length)]
  })
}

// 生成相应数量都为0的数组
const initArray = () => {
  const numbers = Array.from({ length: gridCount }, () => 0)
  gridAttr = numbers

  // 分割数组为二维数组
  const tempGridAttrs: number[][] = []
  for (let i = 0; i < gridSize; i++) {
    tempGridAttrs[i] = gridAttr.slice(i * gridSize, (i + 1) * gridSize)
  }
  gridAttrs.value = tempGridAttrs
}

// 随机数组 -- 开始/重置游戏
const randomArray = () => {
  selectGridIndex.value = 0
  selectedGrids.value = []
  selectError.value = []
  const numbers = Array.from({ length: gridCount }, (_, i) => i + 1)
  gridAttr = numbers.sort(() => Math.random() - 0.5)

  // 分割数组为二维数组
  const tempGridAttrs: number[][] = []
  for (let i = 0; i < gridSize; i++) {
    tempGridAttrs[i] = gridAttr.slice(i * gridSize, (i + 1) * gridSize)
  }
  gridAttrs.value = tempGridAttrs
}

let startDownTimer: any = null
// 开始/重置游戏
const startGame = () => {
  isStart.value = false
  startDown.value = true
  isGameOver.value = false
  startDownCount.value = 3

  startDownTimer = setInterval(() => {
    startDownCount.value--
    if (startDownCount.value < 1) {
      clearInterval(startDownTimer)
      startDown.value = false

      randomArray()

      timer = setInterval(() => {
        let timeSNum: number = Number(timeS.value)
        if (timeSNum == 59) {
          const timeMNum: number = Number(timeM.value) + 1
          if (timeMNum < 10) {
            timeM.value = `0${timeMNum}`
          } else {
            timeM.value = `${timeMNum}`
          }
        }

        timeSNum++
        // 设置时间上限 超过1小时 时间超时 游戏结束
        if (parseFloat(timeM.value) === 60) {
          // 60m:00s
          timeS.value = '00'
          isGameTimeOver.value = true
          clearInterval(timer)
        } else {
          if (timeSNum < 10) {
            timeS.value = `0${timeSNum}`
          } else {
            if (timeSNum == 60) {
              timeS.value = '00'
            } else {
              timeS.value = `${timeSNum}`
            }
          }
        }
      }, 1000)
    }
  }, 1000)
}

// 再次训练
const resetGame = () => {
  touchAudio.stop()
  timeM.value = '00'
  timeS.value = '00'
  selectedGrids.value = []
  selectError.value = []
  startDown.value = false
  isGameOver.value = false
  isStart.value = true
  randomColor()
  initArray()
}

// 退出
const quitGame = () => {
  if (touchAudio) {
    try {
      touchAudio.stop()
      // touchAudio.destroy()
      touchAudio = null
    } catch (e) {
      // ...
    }
  }
  uni.reLaunch({
    url: '/pages/index/index'
  })
}
</script>

<style lang="scss" scoped>
@keyframes startdownanimation {
  0% {
    opacity: 0.2;
    transform: scale(1);
  }

  50% {
    opacity: 1;
    transform: scale(1.5);
  }

  100% {
    opacity: 0;
    transform: scale(1);
  }
}

@keyframes rotatetwo {
  0% {
    transform: scale(0.9);
  }

  50% {
    transform: scale(1);
  }

  100% {
    transform: scale(0.9);
  }
}

.box {
  position: relative;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  width: 100%;
  height: 100vh;
  overflow: hidden;
}

.time-box {
  position: absolute;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 336rpx;
  height: 94rpx;
}

.time {
  position: relative;
  z-index: 3;
  font-size: 48rpx;
  font-style: normal;
  font-weight: 600;
  line-height: 67rpx;
  color: #fff;
  text-align: center;
  text-transform: none;
}

.main {
  width: 100%;
  margin-top: 100rpx;
}

.desc-box {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 102rpx;
  background: #de983f;
  border-radius: 28rpx;
  box-shadow: inset 0rpx 8rpx 4rpx 0rpx #b67523;
}

.desc-text {
  z-index: 2;
  font-size: 48rpx;
  font-style: normal;
  font-weight: 600;
  line-height: 67rpx;
  color: #793b07;
  text-align: center;
  text-transform: none;
}

.desc-text-border {
  position: absolute;
  z-index: 1;
  -webkit-text-stroke: 4rpx #fff;
}

.row-box {
  position: relative;
  z-index: 2;
  width: 100%;
  height: 100%;
  padding: 56rpx 58rpx 104rpx 56rpx;
}

.row {
  display: flex;
  justify-content: space-around;
}

.grid {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  border-top: 0;
  border-right: 0;
  border-bottom: 1rpx solid #c6e1ff;
  border-left: 1rpx solid #c6e1ff;
}

.grid-number {
  z-index: 2;
  font-size: 92rpx;
  font-weight: bold;
  color: #061f3c;
}

.grid-number-border {
  position: absolute;
  z-index: 1;
  -webkit-text-stroke: 8rpx #fff;
}

.row-box .row:first-child {
  .grid {
    border-top: 1rpx solid #c6e1ff;
  }
}

.row-box .row .grid:last-child {
  border-right: 1rpx solid #c6e1ff;
}

.grid-even {
  background-color: #c6e1ff;
}

.grid-odd {
  background-color: #fff;
}

.grid-even-even {
  background-color: #fff;
}

.grid-odd-even {
  background-color: #c6e1ff;
}

.grid-color-1 {
  background-color: #fffcc0;
  border-top: 0 !important;
  border-right: 0 !important;
  border-bottom: 0 !important;
  border-left: 0 !important;
}

.grid-color-2 {
  background-color: #bfdeff;
  border-top: 0 !important;
  border-right: 0 !important;
  border-bottom: 0 !important;
  border-left: 0 !important;
}

.grid-color-3 {
  background-color: #fad6d4;
  border-top: 0 !important;
  border-right: 0 !important;
  border-bottom: 0 !important;
  border-left: 0 !important;
}

.grid-color-4 {
  background-color: #cbfbe7;
  border-top: 0 !important;
  border-right: 0 !important;
  border-bottom: 0 !important;
  border-left: 0 !important;
}

.mode,
.start-box,
.game-over,
.start-down,
.game-time-over {
  position: absolute;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-evenly;
  width: 100%;
  height: 100%;
  background: rgb(0 0 0 / 50%);
}

.start-down {
  background: rgb(0 0 0 / 70%);
}

.start-down-name {
  font-size: 200rpx;
  font-style: normal;
  font-weight: 600;
  color: #fff;
  text-align: center;
  text-shadow: 0 4rpx 0 rgb(0 0 0 / 60%);
  text-transform: none;
  animation: startdownanimation 1s ease-in-out infinite;
}

.mode-name {
  font-size: 48rpx;
  font-style: normal;
  font-weight: 600;
  line-height: 56rpx;
  color: #fff;
  text-align: center;
  text-shadow: 0 4rpx 0 rgb(0 0 0 / 60%);
  text-transform: none;
}

.mode-content {
  display: flex;
  flex-direction: column;
}

.mode-easy,
.mode-primary,
.mode-difficult {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 540rpx;
  height: 137.77rpx;
  margin-bottom: 64rpx;
  animation: rotatetwo 1s infinite;

  .mode-name {
    z-index: 3;
    text-shadow: 0 2rpx 0 rgb(0 0 0 / 60%);
  }
}

.start-box .start-btn,
.reset-btn,
.quit-btn {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 540rpx;
  height: 137.77rpx;
  animation: rotatetwo 1s infinite;

  .mode-name {
    z-index: 3;
    text-shadow: 0 2rpx 0 rgb(0 0 0 / 60%);
  }
}

.grid-selected {
  background-color: rgb(0 0 0 / 40%);
}

.grid-error {
  background-color: rgb(255 0 0 / 40%);
}

.over-box {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-evenly;
  height: 100%;
}

.game-time-over-name {
  font-size: 64rpx;
  font-style: normal;
  font-weight: 600;
  line-height: 75rpx;
  color: #fff;
  text-align: center;
  text-shadow: 0 6rpx 0 rgb(0 0 0 / 60%);
  text-transform: none;
}

.over-main {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;

  .over-name {
    font-size: 64rpx;
    font-style: normal;
    font-weight: 600;
    line-height: 75rpx;
    color: #fff;
    text-align: center;
    text-shadow: 0 6rpx 0 rgb(0 0 0 / 60%);
    text-transform: none;
  }

  .game-time-box {
    display: flex;
    align-items: flex-end;
    margin-top: 72rpx;
  }

  .time-name {
    z-index: 2;
    font-size: 48rpx;
    font-style: normal;
    font-weight: 600;
    line-height: 56rpx;
    color: #fff;
    text-align: center;
    text-shadow: 0rpx 6rpx 0rpx rgb(0 0 0 / 60%);
    text-transform: none;
  }

  .time-name-border {
    position: absolute;
    z-index: 1;
    -webkit-text-stroke: 4rpx #a1c8a7;
  }

  .game-time {
    z-index: 2;
    font-size: 200rpx;
    font-style: normal;
    font-weight: 600;
    line-height: 234rpx;
    color: #fff;
    text-align: center;
    text-shadow: 0 12rpx 0 rgb(0 0 0 / 60%);
    text-transform: none;
  }

  .game-time-border {
    position: absolute;
    z-index: 1;
    -webkit-text-stroke: 4rpx #a1c8a7;
  }
}

.back-image {
  position: absolute;
  z-index: 2;
  width: 100%;
  height: 100%;
}
</style>
